package main

import (
	"peilian-api/app/global/variable"
	_ "peilian-api/bootstrap"

	"fmt"
	"math/rand"
	"os"
	"peilian-api/utils/encrypt"
	"peilian-api/utils/sdk"
	"strings"
	"time"

	"github.com/tealeg/xlsx"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

// 学历是固定的，无需加入数据库
var EducationArr = []string{"大专", "本科", "硕士", "博士"}

// 年级固定
var GradeArr = []string{"2012", "2013", "2014", "2015", "2016", "2017", "2018", "2019", "2020", "2021", "2022", "2023"}

var AgentId = 60
var InserSchool = "上海交通大学"
var SchoolConstituteId = 4329
var Prefix = "SJTU"

var db *gorm.DB
var err error

const (
	userName = "youshi"
	pwd      = "1G?ywxyrlis4Orl"
	ipCode   = "10.9.93.161:3306"
	dbName   = "peilian"
)

// const (
// 	userName = "youshi_t"
// 	pwd      = "2K4adice?sdfrx3e"
// 	ipCode   = "10.9.93.161:3306"
// 	dbName   = "peilian_test_zs"
// )

func generatePwd(sno string) string {
	// 1. 根据学校名称获取学校前缀
	var prefix = Prefix
	// 2. 生成密码
	// rsaPwd, _ := encrypt.RsaEncode(prefix + sno)
	pwd, _ := encrypt.EncryptPassword(prefix + sno)
	return pwd
}

func CreateDB() error {
	dbinfo := strings.Join([]string{userName, ":", pwd, "@tcp(", ipCode, ")/", dbName, "?charset=utf8&parseTime=True&loc=Local"}, "")
	db, err = gorm.Open(mysql.Open(dbinfo), &gorm.Config{
		DisableForeignKeyConstraintWhenMigrating: true,
	})
	if err != nil {
		return err
	}
	return nil
}

func ReadExcle(filepath string) [][][]string {
	out, err := xlsx.FileToSlice(filepath)
	if err != nil {
		panic(err.Error())
	}
	return out
}
func Contains(elements []string, needle string) bool {
	for _, v := range elements {
		if needle == v {
			return true
		}
	}

	return false
}

type Model struct {
	Id        uint           `gorm:"primarykey" json:"id"`
	CreatedAt time.Time      `json:"created_at" format:"2006-01-02 15:04:05"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
}

type Constitute struct {
	Model
	Type       string `json:"type"`
	Name       string `json:"name"`
	BelongToId int    `json:"belong_to_id"`
	AgentId    int    `json:"agent_id"`
}

type Users struct {
	CreatedAt    time.Time `json:"created_at" format:"2006-01-02 15:04:05"`
	UpdatedAt    time.Time `json:"updated_at"`
	Id           int       `json:"id"`
	Name         string    `json:"name"`
	Sno          string    `json:"sno"`
	Password     string    `json:"password"`
	AccountName  *string   `json:"account_name"`
	Type         string    `json:"type"`
	School       string    `json:"school"`
	Academy      string    `json:"academy"`
	Profession   string    `json:"profession"`
	Grade        string    `json:"grade"`
	Education    string    `json:"education"`
	ConstituteID uint      `json:"constitute_id"`
	RoleId       uint      `json:"role_id"`
	AgentID      uint      `json:"agent_id"`
	Phone        string    `json:"phone"`
	Email        string    `json:"mail"`
	Level        int       `json:"level"`
	CreateUserId int       `json:"create_user_id"`
}

var m map[string]int = make(map[string]int, 0)
var t map[string]int = make(map[string]int, 0)
var q map[string]map[string]int = make(map[string]map[string]int, 0)

func dealMap() {
	var c []Constitute
	db.Table("constitute").Where("type = ? and belong_to_id = ?", "academy", SchoolConstituteId).Select("id,name,type,belong_to_id").Find(&c)
	for i := 0; i < len(c); i++ {
		m[c[i].Name] = int(c[i].Id)
		if _, ok := q[c[i].Name]; !ok {
			q[c[i].Name] = make(map[string]int, 0)
			t[c[i].Name] = int(c[i].Id)
		}
		var d []Constitute
		db.Table("constitute").Where("type = ? and belong_to_id = ?", "profession", c[i].Id).Select("id,name,type,belong_to_id").Find(&d)
		for j := 0; j < len(d); j++ {
			q[c[i].Name][d[j].Name] = int(d[j].Id)
		}
	}
}

func analysis(out [][][]string) {
	var errInfo = []string{}
	for i := 1; i < len(out[0]); i++ {
		name := out[0][i][0]
		sno := out[0][i][1]
		// fmt.Println(out[0][i][2]) // 无
		academy := strings.ReplaceAll(strings.ReplaceAll(out[0][i][2], "（", "("), "）", ")")
		profession := strings.ReplaceAll(strings.ReplaceAll(out[0][i][3], "（", "("), "）", ")")
		education := out[0][i][4]
		grade := out[0][i][5]
		if !Contains(GradeArr, grade) {
			errInfo = append(errInfo, sno+",grade不存在")
			continue
		}
		if !Contains(EducationArr, education) {
			errInfo = append(errInfo, sno+",学历不存在")
			continue
		}
		fmt.Println(name, academy, profession)
		var c = Constitute{}
		var count int64
		if _, ok := m[academy]; !ok {
			d := db.Table("constitute").Where("type = ? and name = ? and belong_to_id = ?", "academy", academy, SchoolConstituteId).Select("id,name,type,belong_to_id").Find(&c).Count(&count)
			if d.Error != nil {
				errInfo = append(errInfo, sno+",学院建立错误")
				continue
			}
			if count == 0 { // 插入
				c.CreatedAt = time.Now().UTC()
				c.UpdatedAt = time.Now().UTC()
				c.AgentId = 0
				c.Type = "academy"
				c.BelongToId = SchoolConstituteId
				c.Name = academy
				db.Table("constitute").Create(&c)
				if c.Id == 0 {
					errInfo = append(errInfo, sno+",学院建立错误")
					continue
				}
			}
			m[c.Name] = int(c.Id)
			q[academy] = make(map[string]int, 0)
		}
		if pid, ok := m[academy]; ok {
			if _, okq := q[academy][profession]; !okq {
				var p Constitute
				// 查询专业是否存在
				d := db.Table("constitute").Where("type = ? and name = ? and belong_to_id = ?", "profession", profession, pid).Select("id,name,type,belong_to_id").Find(&p).Count(&count)
				if d.Error != nil {
					errInfo = append(errInfo, sno+",专业建立错误")
					continue
				}
				c = Constitute{}
				var constitute_id = pid
				if count == 0 { // 插入
					c.CreatedAt = time.Now().UTC()
					c.UpdatedAt = time.Now().UTC()
					c.AgentId = 0
					c.Type = "profession"
					c.BelongToId = int(pid)
					c.Name = profession
					db.Table("constitute").Create(&c)
					if c.Id == 0 {
						errInfo = append(errInfo, sno+",专业建立错误")
						continue
					}
					constitute_id = int(c.Id)
				}
				if constitute_id == 0 {
					errInfo = append(errInfo, sno+",专业建立错误")
					continue
				}
				q[academy][profession] = int(c.Id)
			}
		}
	}
	for i := 0; i < len(errInfo); i++ {
		fmt.Println(errInfo[i])
	}

}

// 导入学生
func insertMessage(out [][][]string) {
	for i := 1; i < len(out[0]); i++ {
		academy := out[0][i][0]
		accountName := out[0][i][1]
		name := out[0][i][3]
		phone := out[0][i][4]
		mail := out[0][i][5]
		education := out[0][i][6]
		constituteId := t[academy]

		var user Users
		user.CreatedAt = time.Now().UTC()
		user.UpdatedAt = time.Now().UTC()
		user.Name = name
		user.AccountName = &accountName
		user.Type = "admin"
		user.Phone = phone
		user.Email = mail
		user.Level = 3
		user.CreateUserId = 277674
		user.RoleId = 4
		user.School = InserSchool
		user.Academy = academy
		user.AgentID = uint(AgentId)
		user.ConstituteID = uint(constituteId)
		user.Education = education
		// 发送邮箱
		code := fmt.Sprintf("%06v", rand.New(rand.NewSource(time.Now().UnixNano())).Int31n(1000000))

		user.Password = code
		fmt.Println(user)
		d := db.Table("users").Where("email = ? and school = ?", user.Email, InserSchool).FirstOrCreate(&user)
		if d.Error != nil {
			fmt.Println(d.Error)
		}
		if err := sdk.SendMailInfo(sdk.MsgTypePassword, variable.Config.MailInfo.BusinessMail, sdk.MailInfo{RealName: name, AccountName: accountName, Password: code, MailTo: mail}); err != nil {
			fmt.Println(code)
		}
	}

}

func main() {
	CreateDB()
	dir, _ := os.Getwd()
	filePath := dir + "/scripts/school/admin/sjtu.xlsx"
	s := ReadExcle(filePath)
	dealMap()
	// fmt.Println(s)
	// fmt.Println(t)
	insertMessage(s)
	// analysis(s)
	// dealMap()
	// insertStudent(s)

}
